﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using jaysJourney_v01.Common;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using jaysJourney_v01.Utils;
using Microsoft.Xna.Framework.Input;
using System.Diagnostics;

namespace jaysJourney_v01.States
{
    class WinState : State
    {
        /**
         * MEMBER VARIABLES
         * */

        // From Parent

        private SpriteBatch mainSpriteBatch;
        private PlayState playState;

        // Common

        private InputGroup rateButtonGroup;
        private InputGroup menuButtonGroup;

        private Texture2D userdataBG;
        private Texture2D interfaceBG;
        private Texture2D stars;

        // Buttons

        private Button ratePre;
        private Button rateNext;
        private Button rateWorld;

        private Button restart;
        private Button loadWorld;
        private Button mainMenu;

        

        // Rating

        private float rating = 0f;
        private bool rated = false;
        private MouseState oldM;

        /**
         * METHODS
         * */

        // Constructor

        public WinState(String name, StateManager stateManager) : base(name, stateManager) { }

        // init

        public override void initialize()
        {
            this.mainSpriteBatch = this.parentSpriteBatch;
            this.playState = (PlayState)getStateManager().getState("playState");

            this.interfaceBG = this.getGame().Content.Load<Texture2D>(@"Textures\Interface\main_menu_v5");
            this.userdataBG = this.getGame().Content.Load<Texture2D>(@"Textures\Interface\userdata_bg");

            // Buttons
            //this.ratePre = new Button(this, "ratePrev", @"Textures\Interface\minus_btn", @"Textures\Interface\minus_btn_ac", this.getGame().GraphicsDevice.Viewport.Width / 2 - 150, 350, Color.White, false, false);
            //this.rateNext = new Button(this, "rateNext", @"Textures\Interface\plus_btn", @"Textures\Interface\plus_btn_ac", this.getGame().GraphicsDevice.Viewport.Width / 2 + 100, 350, Color.White, false, false);
            this.rateWorld = new Button(this, "RATE WORLD", @"Textures\Interface\menu_button", @"Textures\Interface\menu_button_ac", 450, Color.White, false, true);

            this.restart = new Button(this, "RESTART", @"Textures\Interface\menu_button", @"Textures\Interface\menu_button_ac", 550, Color.White, false, true);
            this.loadWorld = new Button(this, "LOAD WORLD", @"Textures\Interface\menu_button", @"Textures\Interface\menu_button_ac", 650, Color.White, false, true);
            this.mainMenu = new Button(this, "MAIN MENU", @"Textures\Interface\back_btn", @"Textures\Interface\back_btn_ac", 20, this.getGame().GraphicsDevice.Viewport.Height - 74, Color.White, false, false);
            this.stars = getGame().Content.Load<Texture2D>(@"Textures\Interface\stars");

            this.rateButtonGroup = new InputGroup(this, this.mainSpriteBatch);
            //this.rateButtonGroup.addButton(ratePre);
            //this.rateButtonGroup.addButton(rateNext);
            this.rateButtonGroup.addButton(rateWorld);

            this.menuButtonGroup = new InputGroup(this, this.mainSpriteBatch);
            this.menuButtonGroup.addButton(restart);
            this.menuButtonGroup.addButton(loadWorld);
            this.menuButtonGroup.addButton(mainMenu);

            
        }

        // MAIN UPDATE

        public override void update(GameTime gameTime)
        {

            // update buttons
            Button click = null;
            
            if (!rated)
            {
                /*
                if (playState.getLvlData().getPersonalBest() != 0)
                {
                    rated = true;
                    Console.WriteLine("nope");
                }
                 * */
                if(rating>0)click = this.rateButtonGroup.update(gameTime);
                MouseState m = Mouse.GetState();
                for (int i = 0; i < 5; i++)
                {
                    if (m.LeftButton==ButtonState.Pressed&&oldM.LeftButton==ButtonState.Released&&m.X > this.getGame().GraphicsDevice.Viewport.Width / 2 - 100 + 40 * i && m.X < this.getGame().GraphicsDevice.Viewport.Width / 2 - 100 + 40 * i + 32 && m.Y > 400 && m.Y < 432)
                    {
                        this.rating = i + 1;
                    }
                }
                oldM = m;
            }
            else
            {
                click = this.menuButtonGroup.update(gameTime);
            }

            // handle button clicks
            if (click != null)
            {
                playState = (PlayState)this.getStateManager().getState("playState");

                switch (click.getName())
                {
                    case "ratePrev":
                        if (this.rating > 1) this.rating--;
                        break;
                    case "rateNext":
                        if (this.rating < 5) this.rating++;
                        break;
                    case "RATE WORLD":
                        double rate = (float)((float)(this.rating - playState.getLvlData().getCurRating()) / (float)(playState.getLvlData().getNumRates() + 1f)) + playState.getLvlData().getCurRating();
                        playState.getLvlData().setCurRating((float)rate);
                        playState.getLvlData().setNumRates(playState.getLvlData().getNumRates() + 1);
                        this.getGame().pushMessage("Thank you for rating " + playState.getLvlData().getLevel() + ".", false);
                        rated = true;
                        break;
                    case "RESTART":
                        rated = false;
                        ((PlayState)this.getStateManager().getState("playState")).resetLevel();
                        this.getStateManager().setActiveState("playState");
                        break;
                    case "LOAD WORLD":
                        rated = false;
                        ((LoadWorldState)this.getStateManager().getState("loadWorldState")).loadworldoverview = true;
                        this.getStateManager().setActiveState("loadWorldState");
                        break;
                    case "MAIN MENU":
                        rated = false;
                        this.getStateManager().setActiveState("menuState");
                        break;
                }
            }
        }

        // MAIN DRAW

        public override void draw(GameTime gameTime)
        {
            // draw bg
            this.mainSpriteBatch.Draw(this.getGame().menuBg, new Rectangle(0, 0, this.getGame().GraphicsDevice.Viewport.Width, this.getGame().GraphicsDevice.Viewport.Height), new Rectangle(0, 0, this.getGame().menuBg.Width, this.getGame().menuBg.Height), Color.White);

            // draw interface bg
            if(rated)this.mainSpriteBatch.Draw(this.userdataBG, new Rectangle((this.getGame().GraphicsDevice.Viewport.Width / 2) + 170, 350, this.userdataBG.Width, this.userdataBG.Height), new Rectangle(0, 0, this.userdataBG.Width, this.userdataBG.Height), Color.White);
            this.mainSpriteBatch.Draw(this.interfaceBG, new Rectangle((this.getGame().GraphicsDevice.Viewport.Width / 2) - this.interfaceBG.Width / 2, 0, this.interfaceBG.Width, this.interfaceBG.Height), new Rectangle(0, 0, this.interfaceBG.Width, this.interfaceBG.Height), Color.White);

            // draw btns & txt
            if (!rated)
            {
                String time = "Rate the world";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, time, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(time).X / 2, 310), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, "to continue!", new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString("to continue!").X / 2, 330), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
               
                for (int i = 0; i < 5; i++)
                {
                    mainSpriteBatch.Draw(stars,new Rectangle(this.getGame().GraphicsDevice.Viewport.Width / 2-100+40*i,400,32,32),new Rectangle(0,0,32,32),Color.White);
                    if (i < this.rating) mainSpriteBatch.Draw(stars, new Rectangle(this.getGame().GraphicsDevice.Viewport.Width / 2 - 100 + 40 * i, 400, 32, 32), new Rectangle(32, 0, 32, 32), Color.White);
                }
                if(rating>0)this.rateButtonGroup.draw(gameTime);
                }
            else
            {
                String name = "Stage:";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, name, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(name).X / 2, 250), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, playState.getLvlData().getLevel(), new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(playState.getLvlData().getLevel()).X / 2, 270), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                
                String time = "Your Time:";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, time, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(time).X / 2, 310), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, Formater.formatTime(playState.getCurTime()), new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(Formater.formatTime(playState.getCurTime())).X / 2, 330), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                
                String bestTime = "Your Besttime:";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, bestTime, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(bestTime).X / 2, 370), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, Formater.formatTime(playState.getCurTime()), new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(Formater.formatTime(playState.getCurTime())).X / 2, 390), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                
                String avgTime = "Average Besttime:";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, avgTime, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(avgTime).X / 2, 430), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, Formater.formatTime(playState.getLvlData().getAvgBestTime()), new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(Formater.formatTime(playState.getLvlData().getAvgBestTime())).X / 2, 450), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                
                String overalTime = "Overall Besttime:";
                this.mainSpriteBatch.DrawString(this.getGame().textFont, overalTime, new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(overalTime).X / 2, 490), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, Formater.formatTime(playState.getLvlData().getBestTime()), new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 - this.getGame().textFont.MeasureString(Formater.formatTime(playState.getLvlData().getBestTime())).X / 2, 510), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);

                this.menuButtonGroup.draw(gameTime);
                this.mainSpriteBatch.DrawString(this.getGame().textFont, "Stage already rated!\n\nCurrent Average rating:\n" + round(playState.getLvlData().getCurRating(),2) + " / 5 Stars", new Vector2(this.getGame().GraphicsDevice.Viewport.Width / 2 + 215, 360), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 1f);
               
                
                
            }
        }

        private double round(double number, int decimals)
        {
            number *= Math.Pow(10, decimals);
            number = (int)number;
            number /= Math.Pow(10, decimals);
            return number;
        }
        public override void onEnterState()
        {
            //this.ratePre.setNewPosition(this.getGame().GraphicsDevice.Viewport.Width / 2 - 122, 350);
            //this.rateNext.setNewPosition(this.getGame().GraphicsDevice.Viewport.Width / 2 + 72, 350);
            this.rateWorld.setNewPosition(450);
            this.rating = 0;
            this.restart.setNewPosition(555);
            this.loadWorld.setNewPosition(630);
            this.mainMenu.setNewPosition(20, this.getGame().GraphicsDevice.Viewport.Height - 74);
            
        }

        // update ranking

        public void updateRanking()
        {
            // check global besttime
            if (playState.getCurTime() < playState.getLvlData().getBestTime() || playState.getLvlData().getBestTime() == 0)
            {
                // get money & xp for new bestTime
                this.getGame().activePlayer.setPlayer(this.getGame().activePlayer.getUsername(), this.getGame().activePlayer.getMoney() + 50, this.getGame().activePlayer.getXp() + 25);
                this.getGame().pushMessage("WOW, you just beat the current TimeRecord " + Formater.formatTime(playState.getLvlData().getBestTime()) + " and got extra 50 money and 25 xp.", false);

                playState.getLvlData().setBestTime(playState.getCurTime());
                playState.getLvlData().setRecordHolder(this.getGame().activePlayer.getUsername());
            }

            Console.WriteLine(playState.getLvlData().getPersonalBest());
            if (playState.getLvlData().getPersonalBest() == 0)
            {
                this.rated = false;
            }
            else this.rated = true;
            // check personal besttime
            if (playState.getCurTime() < playState.getLvlData().getPersonalBest() || playState.getLvlData().getPersonalBest() == 0)
            {
                // get money & xp for new personal besttime
                this.getGame().activePlayer.setPlayer(this.getGame().activePlayer.getUsername(), this.getGame().activePlayer.getMoney() + 30, this.getGame().activePlayer.getXp() + 25);

                if (playState.getLvlData().getPersonalBest() == 0) WebSaver.createPersonalBestTime(this.getGame().activePlayer.getUsername(), playState.getLvlData().getLevel(), playState.getCurTime());
                else WebSaver.updatePersonalBestTime(this.getGame().activePlayer.getUsername(), playState.getLvlData().getLevel(), playState.getCurTime());
                
                this.getGame().pushMessage("GratZ, you just beat your old personal TimeRecord " + Formater.formatTime(playState.getLvlData().getPersonalBest()) + " and got extra 30 money and 25 xp.", false);

                playState.getLvlData().setPersonalBest(playState.getCurTime());

                // recalculate avg besttime
                playState.getLvlData().setAvgTime((int)((float)((float)(playState.getCurTime() - playState.getLvlData().getAvgBestTime()) / (float)(playState.getLvlData().getNumRates() + 1f)) + playState.getLvlData().getAvgBestTime()));
            }

            // get money & xp for finishing stage
            this.getGame().activePlayer.setPlayer(this.getGame().activePlayer.getUsername(), this.getGame().activePlayer.getMoney() + 20, this.getGame().activePlayer.getXp() + 25);
            WebSaver.userUpdate(this.getGame().activePlayer.getUsername(), this.getGame().activePlayer.getMoney(), this.getGame().activePlayer.getXp());
            this.getGame().pushMessage("You got 20 money and 25 xp for finishing " + playState.getLvlData().getLevel() + ".", false);

            // update creator
            WebSaver.creatorUpdate(playState.getLvlData().getCreatorName());

            // update world
            WebSaver.worldUpdate(playState.getLvlData().getLevel(), playState.getLvlData().getNumStarts(), playState.getLvlData().getNumRates(), playState.getLvlData().getCurRating(), playState.getLvlData().getBestTime(), playState.getLvlData().getRecordHolder(), playState.getLvlData().getAvgBestTime());
        }
    }
}